package org.androbuzz;

import java.util.ArrayList;
import java.util.List;

import android.R.integer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.text.Editable;
import android.util.Log;


/**
 * @author pilo, Quentin Desert, Nicolas Boutin, Xavier Lamien
 *
 */
public class AndroBuzzDbAdapter {

	private static class DatabaseHelper extends SQLiteOpenHelper {

		DatabaseHelper(Context context) {
			super(context, DATABASE_NAME, null, DATABASE_VERSION);
		}

		@Override
		public void onCreate(SQLiteDatabase db) {
			Log.w(TAG, "onCreate ");
			db.execSQL(DATABASE_CREATE_BUZZES);
			db.execSQL(DATABASE_CREATE_MEDIAS);
			db.execSQL(DATABASE_CREATE_AUTHOR);
			db.execSQL(DATABASE_CREATE_COMMENTS);
			db.execSQL(DATABASE_CREATE_PROFILES);
			db.execSQL(DATABASE_CREATE_BUDDIES);
		}

		@Override
		public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
			Log.w(TAG, "Upgrading database from version " + oldVersion + " to "
					+ newVersion + ", which will destroy all old data");
			db.execSQL("DROP TABLE IF EXISTS buzzes");
			db.execSQL("DROP TABLE IF EXISTS medias");
			db.execSQL("DROP TABLE IF EXISTS authors");
			db.execSQL("DROP TABLE IF EXISTS comments");
			db.execSQL("DROP TABLE IF EXISTS profiles");
			db.execSQL("DROP TABLE IF EXISTS buddies");
			onCreate(db);
		}
	}
	
	public static final String KEY_FEED_ID 			= "feed_id";
	public static final String KEY_GOOGLE_BUZZ_ID 	= "google_buzz_id";
	public static final String KEY_AUTHOR 			= "author_id";
	public static final String KEY_AUTHOR_NAME		= "author_name";
	public static final String KEY_PROFILES_ID      = "profiles_id";
	public static final String KEY_DATE 			= "publication_date";
	public static final String KEY_SUMMARY 			= "summary";
	public static final String KEY_CONTENT 			= "content";
	public static final String KEY_NB_COMMENTS		= "nb_comments";
	public static final String KEY_ROWID 			= "_id";
	public static final String KEY_BUDDIES_NAME     = "name";
	public static final String KEY_BUDDIES_EMAIL    = "email";

	private static final String TAG 				= "AndroBuzzDbAdapter";
	private DatabaseHelper mDbHelper;

	private SQLiteDatabase mDb;
	/**
	 * Database creation SQL statement
	 */
	private static final String DATABASE_CREATE_BUZZES =
		"create table 	buzzes ("
		+ "_id 					integer primary key autoincrement, "
		+ "feed_id 				text 		not null,"
		+ "google_buzz_id		text 		not null,"
		+ "author_id 			integer		not null," // RowId of the author
		+ "publication_date 	text 		not null,"
		+ "content 				text 		not null,"
		+ "summary 				text 		not null,"
		+ "nb_comments 			text		not null)";		// will be an int (which thus can be null) - to modify later

	private static final String DATABASE_CREATE_MEDIAS =
		"create table 	medias ("
		+ " _id					integer primary key autoincrement, "
		+ " buzz_id				integer		not null,"	
		+ " url					text		not null,"
		+ " width				text				,"
		+ " height				text				,"
		+ " kind				text		not null,"
		+ " type				text		not null)";	
	
	private static final String DATABASE_CREATE_AUTHOR =
		"create table 	authors ("
		+ "_id 					integer primary key autoincrement, "
		+ "google_id			text		not null,"		//google id for an author like androbuzz (without @gmail.com)
		+ "google_id_key		text		not null,"
		+ "name					text 		not null," 
		+ "photo_url			text 		not null,"
		+ "update_time			text		not null,"			
		+ "follow 				bool 		not null)";
	
	private static final String DATABASE_CREATE_COMMENTS =
		"create table 	comments ("
		+ "_id					integer primary key autoincrement, "
		+ "content				text 		not null,"
		+ "buzz_id 				integer		not null," // RowId of the buzz
		+ "comment_id			text		not null," //id of the comment
		+ "author_id 			integer		not null," // RowId of the author
		+ "like					bool 		not null,"
		+ "publication_date 	text 		not null)";

	private static final String DATABASE_CREATE_PROFILES =
		"create table	profiles ("
		+ "_id 					integer primary key autoincrement,"
		+ "login				text		not null UNIQUE,"
		+ "token				text		not null,"
		+ "token_secret			text		not null,"
		+ "token_verifier		text		not null,"
		+ "selected				bool		not null)";
	
	private static final String DATABASE_CREATE_BUDDIES =
		"create table   buddies ("
		+ "_id					integer primary key autoincrement,"
		+ "name                 text        not null,"
		+ "email				text		not null UNIQUE,"
		+ "profiles_id          integer     not null)";
	
	private static final String DATABASE_NAME 			= "androbuzz";
	private static final String DATABASE_TABLE_BUZZES 	= "buzzes";
	private static final String DATABASE_TABLE_BUZZES_ID= "buzz_id";
	private static final String DATABASE_TABLE_MEDIAS 	= "medias";
	private static final String DATABASE_TABLE_AUTHOR 	= "authors";
	private static final String DATABASE_TABLE_AUTHOR_ID= "author_id";
	private static final String DATABASE_TABLE_COMMENTS	= "comments";
	private static final String DATABASE_FIELD_CONTENT	= "content";
	private static final String DATABASE_FIELD_LIKE		= "like";
	private static final String DATABASE_FIELD_DATE		= "publication_date";
	private static final String DATABASE_TABLE_PROFILES	= "profiles";
	private static final String DATABASE_TABLE_BUDDIES  = "buddies";
	private static final int 	DATABASE_VERSION		= 14;
	private final Context mCtx;
	
	private boolean mAuthorWasCleaned = false;

	/**
	 * Constructor - takes the context to allow the database to be
	 * opened/created
	 * 
	 * @param ctx the Context within which to work
	 */
	public AndroBuzzDbAdapter(Context ctx) {
		this.mCtx = ctx;
	}
	
	/**
	 * Open the androbuzz database. If it cannot be opened, try to create a new
	 * instance of the database. If it cannot be created, throw an exception to
	 * signal the failure
	 * 
	 * @return this (self reference, allowing this to be chained in an
	 *         initialization call)
	 * @throws SQLException if the database could be neither opened or created
	 */
	public AndroBuzzDbAdapter open() throws SQLException {
		mDbHelper 	= new DatabaseHelper(mCtx);
		mDb 		= mDbHelper.getWritableDatabase();
		Log.d(TAG, "******* mDb pointer: "+ mDb);
		//mDbHelper.onUpgrade(mDb, 3, 4);								// Uncomment this for reinit database

		return this;
	}
	
	public void close() {
		mDbHelper.close();
	}
	
	/**
	 * Create a new buzz using the feed_id, buzz_id, author, date and content provided. If the buzz is
	 * successfully created return the new rowId for that buzz, otherwise return
	 * a -1 to indicate failure.
	 *
	 * @param feed_id the google id of the feed containing this buzz
	 * @param google_buzz_id the google id of the buzz
	 * @param author the author of the buzz
	 * @param date the date of the buzz
	 * @param summary the summary of the buzz
	 * @param content the content of the buzz
	 * @param nb_comments the number of comments of the buzz
	 * @return rowId or -1 if failed
	 */	
	public long createOrUpdateBuzz(String feed_id, String google_buzz_id, String author_id, String date, String summary, String content, String nb_comments) {
		Log.w(TAG, "createBuzz ("+ google_buzz_id +") for author :"+author_id);
		
		long internal_buzzes_id = findBuzzByGoogleBuzzId(google_buzz_id);
		
		if (internal_buzzes_id != -1)
		{
			Log.w(TAG, "This buzz : "+google_buzz_id+" is already in our DB with _id : "+internal_buzzes_id+", we update it");
			//updateBuzz(internal_buzzes_id, google_buzz_id, author, author_google_id, author_google_id, date, summary, content, nb_comments);
			return internal_buzzes_id;
		}
		
//		Log.w(TAG, "createOrUpdateBuzz adding Buzz , google_buzz_id : "+google_buzz_id);

		ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_FEED_ID			, feed_id);
		initialValues.put(KEY_GOOGLE_BUZZ_ID	, google_buzz_id);
		initialValues.put(KEY_AUTHOR			, author_id);
		initialValues.put(KEY_DATE				, date);
		initialValues.put(KEY_SUMMARY			, summary);
		initialValues.put(KEY_CONTENT			, content);
		initialValues.put(KEY_NB_COMMENTS		, nb_comments);
		
		long buzzRowId = mDb.insert(DATABASE_TABLE_BUZZES, null, initialValues);
		
		
		
		return buzzRowId;
	}
	
	
	
	public long createOrUpdateBuzz(String feed_id, String author_id, AndroBuzzSAXHandler.Activity buzz) {
		Log.w(TAG, "createBuzz ("+ buzz.activityId +") for author :"+author_id);
		
		long internal_buzzes_id = findBuzzByGoogleBuzzId(buzz.activityId);
		
		if (internal_buzzes_id != -1)
		{
			Log.w(TAG, "This buzz : "+buzz.activityId+" is already in our DB with _id : "+internal_buzzes_id+", we update it");
			//updateBuzz(internal_buzzes_id, google_buzz_id, author, author_google_id, author_google_id, date, summary, content, nb_comments);
			return internal_buzzes_id;
		}
		
//		Log.w(TAG, "createOrUpdateBuzz adding Buzz , google_buzz_id : "+google_buzz_id);

		ContentValues initialValues = new ContentValues();
		initialValues.put(KEY_FEED_ID			, feed_id);
		initialValues.put(KEY_GOOGLE_BUZZ_ID	, buzz.activityId);
		initialValues.put(KEY_AUTHOR			, author_id);
		initialValues.put(KEY_DATE				, buzz.date_published);
		initialValues.put(KEY_SUMMARY			, buzz.summary);
		initialValues.put(KEY_CONTENT			, buzz.content);
		initialValues.put(KEY_NB_COMMENTS		, buzz.nb_comments);
		
		long buzzRowId = mDb.insert(DATABASE_TABLE_BUZZES, null, initialValues);
		
		if(buzzRowId != -1)
		{
			for(AndroBuzzSAXHandler.Media media: buzz.mediaList)
			{
				if(media.url != null && media.kind != null && media.type != null)
				{
					ContentValues mediaValues = new ContentValues();
					mediaValues.put("buzz_id"				, buzzRowId);
					mediaValues.put("url"					, media.url);
					mediaValues.put("width"				, media.width);
					mediaValues.put("height"				, media.height);
					mediaValues.put("kind"				, media.kind);
					mediaValues.put("type"				, media.type);		
					
					if(mDb.insert(DATABASE_TABLE_MEDIAS, null, mediaValues) == -1)
						Log.e("AndroBuzz DbAdapter", "cannot add media: " + buzzRowId + " " + 
								media.url + " " + media.width + " " + media.height + " " +
								media.kind + " " + media.type);
				}
			}
		}
		
		return buzzRowId;
	}
	
	
	
	
	public long getAuthorCreateOrUpdateIfn(String google_buzz_id_key, String google_buzz_id_name, String author_name, String author_photo_url, String update_time)
	{
		
		long author_key_id = -1;
		long author_name_id = -1;
		
		do
		{
			mAuthorWasCleaned = false;
			if(google_buzz_id_key != null)
				author_key_id = findAuthorByName(google_buzz_id_key);
			
			if(google_buzz_id_name != null)
				author_name_id = findAuthorByName(google_buzz_id_name);	
		} while(mAuthorWasCleaned);
		
		//no author found
		if(author_key_id == -1 && author_name_id == -1)
		{
			return addAuthor(author_name, google_buzz_id_name, google_buzz_id_key, author_photo_url, update_time);
		}
		
		long currentId = author_key_id;
		if(currentId == -1)
			currentId = author_name_id;
		
		updateAuthorIDFull(currentId, google_buzz_id_key, google_buzz_id_name, author_name, author_photo_url, update_time);
			
		return currentId;
	}
	
	/**
	 * Update the buzz using the details provided. The buzz to be updated is
	 * specified using the rowId (buzz_id) , and it is altered to use the author, date and content
	 * values passed in
	 * 
	 * @param buzz_id 			id of buzz to update : entry point.
	 * @param feed_id 			value to set feed google id to
	 * @param google_buzz_id 	value to set buzz google id to
	 * @param author 			value to set buzz author to
	 * @param date 				value to set buzz date to
	 * @param summary 			value to set buzz summary to
	 * @param content 			value to set buzz content to
	 * @param nb_comments		value to set buzz number of comments to
	 * @return true if the buzz was successfully updated, false otherwise
	 */
	public boolean updateBuzz(long buzz_id, String google_buzz_id, String author, String author_google_id, String author_google_id_key, String date, String summary, String content, String nb_comments) {
		ContentValues args = new ContentValues();
		
		long author_id = -1;
		do
		{
			mAuthorWasCleaned = false;
			author_id = findAuthorByName(author_google_id);
			if (author_id == -1)
				author_id = findAuthorByName(author_google_id_key);
		} while (mAuthorWasCleaned);
		
		if (author_id == -1)
			return false;
		//an author can change on update ???
			//author_id = addAuthor(author, author_google_id);

		/*args.put(KEY_FEED_ID, buzz_id);*/
		args.put(KEY_GOOGLE_BUZZ_ID	, google_buzz_id);
		args.put(KEY_AUTHOR			, author_id);
		args.put(KEY_DATE			, date);
		args.put(KEY_SUMMARY		, summary);
		args.put(KEY_CONTENT		, content);
		args.put(KEY_NB_COMMENTS	, nb_comments);

		return mDb.update(DATABASE_TABLE_BUZZES, args, KEY_ROWID + "=" + buzz_id, null) > 0;
	}

	/**
	 * Delete the buzz with the given rowId
	 * 
	 * @param rowId id of buzz to delete
	 * @return true if deleted, false otherwise
	 */
	public boolean deleteBuzz(long rowId) {

		return mDb.delete(DATABASE_TABLE_BUZZES, KEY_ROWID + "=" + rowId, null) > 0;
	}

	/**
	 * Return a Cursor over the list of all buzzes in the database
	 * 
	 * @return Cursor over all buzzes
	 */
	public Cursor fetchAllBuzzes() {
		Log.w(TAG, "fetchAllBuzzes");
		String sql = "SELECT  b._id, b.feed_id, b.google_buzz_id, a.name as '"+KEY_AUTHOR_NAME+"', b.publication_date, b.summary, b.content, b.nb_comments "+
		"FROM buzzes b, authors a where b.author_id = a._id ORDER BY b.publication_date DESC";
		Cursor mCursor = mDb.rawQuery(sql, null);
		if (mCursor != null) {
			mCursor.moveToFirst();
		}
		return mCursor;
	}
	
	/**
	 * Return a Cursor over the list of all buzzes of an author in the database
	 * @param author 		input, restrict search to this author.
	 * @return Cursor over all buzzes
	 */
	public Cursor fetchAllBuzzes(String author_google_id) {
		Log.w(TAG, "fetchAllBuzzes for : " + author_google_id);
		String sql = "SELECT  b._id, b.feed_id, b.google_buzz_id, a.name as '"+KEY_AUTHOR_NAME+"', b.publication_date, b.summary, b.content, b.nb_comments "+
		"FROM buzzes b, authors a where b.author_id = a._id"+
		" AND a.google_id ='" + author_google_id + "' ORDER BY b.publication_date DESC";
		Cursor mCursor = mDb.rawQuery(sql, null);
		if (mCursor != null) {
			mCursor.moveToFirst();
		}
		return mCursor;
	}
	
	/**
	 * Return a Cursor over the list of all buzzes of an author list in the database
	 * @param author 		input, restrict search to this author.
	 * @return Cursor over all buzzes, null if author_google_id_list is empty
	 */
	public Cursor fetchAllBuzzes(List<String> author_google_id_list) {
		if(author_google_id_list.size() > 0)
		{
			boolean firstCont = true;
			Log.i(TAG, "fetchAllBuzzes for : " + author_google_id_list);
			String sql = "SELECT  b._id, b.feed_id, b.google_buzz_id, a.name as '"+KEY_AUTHOR_NAME+"', b.publication_date, b.summary, b.content, b.nb_comments "+
			"FROM buzzes b, authors a where b.author_id = a._id"+
			" AND (";
			for(String author_google_id : author_google_id_list)
			{
				if(!firstCont)
					sql += " OR ";
				else
					firstCont = false;
				sql += "a.google_id ='" + author_google_id + "'";
			}
			
			sql += ") ORDER BY b.publication_date DESC";

			Cursor mCursor = mDb.rawQuery(sql, null);
			if (mCursor != null) {
				mCursor.moveToFirst();
			}
			return mCursor;
		}
		else
			Log.e(TAG, "author_google_id_list is empty cannot query !");
		return null;
	}

	/**
	 * Return a Cursor positioned at the buzz that matches the given rowId
	 * 
	 * @param rowId id of buzz to retrieve
	 * @return Cursor positioned to matching buzz, if found
	 * @throws SQLException if buzz could not be found/retrieved
	 */
	public Cursor fetchBuzz(long rowId) throws SQLException {
		//Changing query to match fetchAllBuzz query
		/**Cursor mCursor =
			mDb.query(true, DATABASE_TABLE_BUZZES, new String[] {KEY_ROWID,
					KEY_FEED_ID, KEY_GOOGLE_BUZZ_ID, KEY_AUTHOR_NAME, KEY_DATE, KEY_CONTENT}, KEY_ROWID + "=" + rowId, null,
					null, null, null, null);*/
			String sql = "SELECT  b._id, b.feed_id, b.google_buzz_id, a.name as '"+KEY_AUTHOR_NAME+"', b.publication_date, b.summary, b.content, b.nb_comments "+
			"FROM buzzes b, authors a where b.author_id = a._id AND b._id =" + rowId;
			Cursor mCursor = mDb.rawQuery(sql, null);
			if (mCursor != null) {
				mCursor.moveToFirst();
			}
		return mCursor;
	}
	
	/**
	 * Add an author
	 * 
	 * @param author author name.
	 * @param follow do you follow this person.
	 * @return the row ID of the newly inserted row, or -1 if an error occurred
	 */
	public long addAuthor(String author, String author_google_id, String author_google_id_key, String author_photo_url, String update_time)
	{
		return addAuthor(author, author_google_id, author_google_id_key, author_photo_url, update_time, false);
	}
	
	/**
	 * Add an author
	 * 
	 * @param author author name.
	 * @param follow do you follow this person.
	 * @return the row ID of the newly inserted row, or -1 if an error occurred
	 */
	public long addAuthor(String author, String author_google_id, String author_google_id_key, String author_photo_url, String update_time, boolean follow)
	{
		ContentValues initialValues = new ContentValues();
		if(author != null)
			initialValues.put("name"	, author);
		else
			initialValues.put("name"	, "");
		
		if(author_google_id != null)
			initialValues.put("google_id", author_google_id);
		else
			initialValues.put("google_id", "");
		
		if(author_google_id != null)
			initialValues.put("photo_url", author_photo_url);
		else
			initialValues.put("photo_url", "");
		
		if(author_google_id_key != null)
			initialValues.put("google_id_key", author_google_id_key);
		else
			initialValues.put("google_id_key", "");
		
		initialValues.put("update_time", update_time);
		
		initialValues.put("follow"	, follow);

		return mDb.insert(DATABASE_TABLE_AUTHOR, null, initialValues);
	}
	
	/**
	 * modify an existing author
	 * @param author_id inuput : the ID to modify
	 * @param author_google_id_key the new value.
	 * @return true if author modified.
	 */
	public boolean updateAuthorIDFull(long author_id, String author_google_id_key, String author_google_id_name, String author_name, String author_photo_url, String update_time)
	{
		ContentValues args = new ContentValues();
		if(author_google_id_key != null)
			args.put("google_id_key", author_google_id_key);
		if(author_google_id_name != null)
			args.put("google_id", author_google_id_name);
		
		if(!(mDb.update(DATABASE_TABLE_AUTHOR, args, KEY_ROWID + "=" + author_id, null) > 0))
			return false;
		
		args.clear();
		
		if(author_name != null)
			args.put("name", author_name);
		if(author_photo_url != null)
			args.put("photo_url", author_photo_url);
		
		args.put("update_time", update_time);
		
		mDb.update(DATABASE_TABLE_AUTHOR, args, KEY_ROWID + "=" + author_id + " AND update_time <'" + update_time + "'", null);
		
		return true;
	}
	
	/**
	 * modify an existing author
	 * @param author_id inuput : the ID to modify
	 * @param follow the new value.
	 * @return true if author modified.
	 */
	public boolean modAuthor(long author_id, boolean follow)
	{
		ContentValues args = new ContentValues();
		args.put(KEY_FEED_ID, follow);
		return mDb.update(DATABASE_TABLE_AUTHOR, args, KEY_ROWID + "=" + author_id, null) > 0;
	}

	/**
	 * @param author input the String of the author to modify.
	 * @param follow the new value
	 * @return true if author has been modified.
	 */
	public boolean modAuthor(String author_google_id, boolean follow){
		long author_id = findAuthorByName(author_google_id);
		if (author_id == -1)
		{
			Log.w(TAG, "modAuthor ("+ author_google_id +") author not found.");
			return false;
		}
		
		return (modAuthor(author_id, follow));
	}
	
	// For the moment this function is useless, we need more information (like email address)
	public Cursor getAllBuddies(){
		String sql = "SELECT * from " + DATABASE_TABLE_BUDDIES;
		
		Cursor mCursor = mDb.rawQuery(sql, null);
		if (mCursor != null) {
			mCursor.moveToFirst();
		}
		return mCursor;
	}
	
		
	/**
	 * Internal function to add a comment on table.
	 * @param author_id				the rowId of the author
	 * @param publication_date 		the date of the comment.
	 * @param content 				the comment.	
	 * @param like					this comment is a like one.
	 * @param buzz_id				the rowId of the buzz.
	 * @return
	 */
	public long addComment(String comment_id, String author_id, String publication_date, String content, boolean like, Long buzz_id)
	{
		ContentValues initialValues = new ContentValues();
		//Log.w(TAG, "Add comment: comment_id " + comment_id + " author_id " + author_id + " date " + publication_date + " content " + content + " buzz_id " + buzz_id);
		initialValues.put(DATABASE_TABLE_BUZZES_ID		, buzz_id);
		initialValues.put(DATABASE_TABLE_AUTHOR_ID		, author_id);
		initialValues.put(DATABASE_FIELD_CONTENT		, content);
		initialValues.put(DATABASE_FIELD_LIKE			, like);
		initialValues.put(DATABASE_FIELD_DATE			, publication_date);
		initialValues.put("comment_id"					, comment_id);
		return mDb.insert(DATABASE_TABLE_COMMENTS, null, initialValues);
	}

	/**
	 * Add a comment to a buzz with like and follow set to false.
	 * 
	 * @param author 				the author name.
	 * @param publication_date 		the date of the comment.
	 * @param content 				the comment.
	 * @param google_buzz_id 		the google buzz id.
	 * @return rowId of the new comment.
	 */
	public long addComment(String comment_id, String author_id, String publication_date, String content, String google_buzz_id)
	{
		boolean like 		= false;
		boolean autofollow 	= false; // only for new author

		return addComment(comment_id, author_id, publication_date, content, google_buzz_id, like, autofollow);
	}

	/**
	 * Full parameters add comment.
	 * @param author 			the author name.
	 * @param publication_date 	the date of the comment.
	 * @param content 			the comment.
	 * @param google_buzz_id 	the google buzz id.
	 * @param like				this comment is a like one.
	 * @param autofollow		if author is new, follow it by default.
	 * @return rowId of the new comment.
	 */
	public long addComment(String comment_id, String author_id, String publication_date, String content, String google_buzz_id, boolean like, boolean autofollow)
	{
		long internal_buzz_id = findBuzzByGoogleBuzzId(google_buzz_id);


		if (internal_buzz_id == -1)
		{
			Log.w(TAG, "addComment on buzz_id : "+google_buzz_id+" but no buzz found in our DB. Comment skip");
			return -1;
		}
		return addComment(comment_id, author_id, publication_date, content, like, internal_buzz_id);

	}
	
	/** 
	 *  Add Google Account into Profile list.
	 *  @param login		Registered Google login.
	 *  @param selected		Current active login.
	 *  @return The row ID of the newly inserted row, or -1 if an error occured.
	 */
	public long addProfile(String login, boolean selected) {
		ContentValues initialValues = new ContentValues();
		
		
		Log.d(TAG, "**** mDb pointer raw:"+ mDb);
		initialValues.put("login", login);
		if(selected){
			initialValues.put("selected", "1");
		}else {
			initialValues.put("selected", "0");
		}
		initialValues.put("token", "");
		initialValues.put("token_secret", "");
		initialValues.put("token_verifier", "");
		
		Log.d(TAG, "Adding new account: " + login);
		if(mDb == null){
			Log.d(TAG, "****** DB pointer null");
		}
		return mDb.insert(DATABASE_TABLE_PROFILES, null, initialValues); 
	}
	
	/**
	 * Add Token for current login.
	 * @param token				Requested Token from Oauth.
	 * @param tokenSecret		Fetched Token secret from Oauth.
	 * @param tokenVerifier		Fetched Key verifier from Request Authorization.
	 * @return The row ID of the newly inserted row, or -1 if an error occured.
	 */
	public long addToken(String token, String tokenSecret, String tokenVerifier) {
		ContentValues initialValues = new ContentValues();
		
		initialValues.put("token", token);
		initialValues.put("token_secret", tokenSecret);
		initialValues.put("token_verifier", tokenVerifier);
		Log.d(TAG, "inserting Token infos into DB");
		return mDb.update(DATABASE_TABLE_PROFILES, initialValues, "selected = 1", null);
	}
	
	/**
	 * Get authorized token for current login
	 * @return The token access for current login.
	 */
	public String getToken() {
		String sql = "SELECT token FROM " + DATABASE_TABLE_PROFILES + " WHERE selected = 1";
		
		Cursor c = mDb.rawQuery(sql, null);
		String token = null;
		int count = c.getCount();
		
		if (count == 1) {
			c.moveToFirst();
			int tokenId = c.getColumnIndex("token");
			Log.d(TAG, "Found Token: " + c.getString(tokenId));
			
			token = c.getString(tokenId) ;
		}
		else if(count == 0) {
			Log.d(TAG, "No token found for current login");
			token =  "";
		}
		c.close();
		return token;
	}
	
	/**
	 * Update current selected login name.
	 * @param login New login requested.
	 * @return The row ID of the newly selected row, or -1 if an error occurred.
	 */
	public void updateProfileLogin(String login) {
		ContentValues values = new ContentValues();
		values.put("login", login);
		
		mDb.update(DATABASE_TABLE_PROFILES, values, "selected = '1'", null);
	}
	
	/**
	 * Deselect previous selected login as default one.
	 * @param name Previous selected login
	 */
	public void unsetDefaultProfile(String name){
		ContentValues values = new ContentValues();
		values.put("selected", "0");
		Log.d(TAG, "Unset default login on " + name);
		mDb.update(DATABASE_TABLE_PROFILES, values, "login = '"+name+"'", null);
	}
	
	/**
	 * Set requested login as current one by make it default.
	 * @param name Current login requested.
	 */
	public void setDefaultProfile(String name){
		ContentValues values = new ContentValues();
		values.put("selected", "1");
		Log.d(TAG, "set default login on " + name);
		mDb.update(DATABASE_TABLE_PROFILES, values, "login = '"+name+"'", null);
	}
	
	// TODO: Use functions above instead. let's no reinvent the wheel.
	public void updateProfileStatus(boolean selected, String currentLogin,  String newLogin) {
		ContentValues values = new ContentValues();
		
		// Unset current active login
		values.put("selected", false);
		Log.d(TAG, "Unset default login on " + currentLogin);
		mDb.update(DATABASE_TABLE_PROFILES, values, "login = '"+ currentLogin +"'", null);
		
		// Set new active login
		values.clear();
		values.put("selected", "1");
		Log.d(TAG, "Set "+ newLogin + " as default with values :" + values);
		mDb.update(DATABASE_TABLE_PROFILES, values, "login =" + "'" + newLogin + "'" , null);
	}
	
	/**
	 * Get a list of stored profile login.
	 * @return Login list of registered profile.
	 */
	public List<String> findProfilesByName() {
		List<String> profiles = new ArrayList<String>();
		String sql = "SELECT login from " + DATABASE_TABLE_PROFILES;
		
		Cursor c = mDb.rawQuery(sql, null);
		if (c.getCount() > 0) {
			c.moveToFirst();
			do {
				profiles.add(c.getString(c.getColumnIndex("login")));
			}while (c.moveToNext());
		}
		Log.d(TAG, "Available Profiles: " + profiles);
		c.close();
		return profiles;
	}
	
	/**
	 * Get current active login from profile list.
	 * @return Current active profile.
	 */
	public String findCurrentProfileId() {

		String profileId = null;
		String sql = "SELECT _id from " + DATABASE_TABLE_PROFILES + " WHERE selected = '1'";
		Cursor c = mDb.rawQuery(sql, null);
		int count = c.getCount();
		if (count == 1) {
			c.moveToFirst();
			int id = c.getColumnIndex("_id");
			profileId = c.getString(id);
			
			Log.d(TAG, "Find ID: " + profileId);
		}
		else if(count == 0) {
			profileId =  "";
		}
		else
			Log.e(TAG, "Multiple selected account !!!");
		Log.d(TAG, "Profile Id from Cursor: " + profileId);
		Log.d(TAG, "Current Login ID: " + profileId);
		c.close();
		return profileId;
	}
	
	/**
	 * Add new Followers/Following into Buddies list
	 * @param name The name of the new Follower/Following
	 * @param email The email of the new Follower/Following
	 * @param profileId The profile ID of current active account
	 * @return The row ID of the newly selected row, or -1 if an error occurred.
	 */
	public long addBuddy(String name, String email, String profileId) {
		ContentValues initialValues = new ContentValues();
		
		Log.d(TAG, "profile ID: " + profileId);
		initialValues.put("name", name);
		initialValues.put("email", email);
		initialValues.put("profiles_id", profileId);
		
		Log.d(TAG, "Add new buddy <" +email+ "> to database");
		return mDb.insert(DATABASE_TABLE_BUDDIES, null, initialValues);
	}
	
	/**
	 * Retrieve requested Followers/Following for current active account
	 * @param profileId The profile ID of current active account
	 * @return cursor data of selected row ID.
	 */
	public Cursor findBuddiesByName(String profileId) {
		String sql = "SELECT _id, name, email FROM " + DATABASE_TABLE_BUDDIES + " WHERE profiles_id= '" + profileId + "'";
		
		Cursor mCursor = mDb.rawQuery(sql, null);
		if (mCursor != null) {
			mCursor.moveToFirst();
		}
		return mCursor;
	}

	/**
	 * Maybe useless
	 * @param google_buzz_id	the google id of the buzz.
	 * @param withLike			count with like or not.
	 * @return number of comment.
	 */
	public int getCommentCountByGoogleBuzzeId(String google_buzz_id, boolean withLike)
	{
		String sql = "SELECT  count(b._id) as 'NB_BUZZES'"+
		"FROM buzzes b, comment c where c.buzz_id = b._id" + 
		"AND b.google_buzz_id = '"+google_buzz_id+"'";
		Cursor mCursor = mDb.rawQuery(sql, null);
		int nb;
		if (mCursor != null) {
			mCursor.moveToFirst();
			nb = mCursor.getInt(0);
		}else
			nb = -1;
		mCursor.close();
		return nb;
	}
	
	/**
	 * Return a row of the author
	 * 
	 * @return Row id of the Author id founded or -1 if not.
	 */
	public long findAuthorByName(String google_buzz_id)
	{
		long author_id = -1;
		String sql = "SELECT * FROM authors WHERE google_id = '"+ google_buzz_id +"' OR google_id_key = '"+ google_buzz_id +"'" ;
		Cursor c = mDb.rawQuery(sql, null);
		int count = c.getCount();
		if (count == 1){
			c.moveToFirst();
			int idx 	= c.getColumnIndex("_id");
			author_id 	= c.getLong(idx);
		}
		else if(count > 1){
			//launch cleaner here TODO
			Log.w(TAG, "findAuthor name: "+ google_buzz_id + "-> more than one author found :"+count + "Cleaning...");
			
			//all authors are incomplete
			String google_id_key = null;
			String google_id = null;
			String author_name = null;
			String photo_url = null;
			c.moveToFirst();
			String update_time = c.getString(c.getColumnIndex("update_time"));
			author_id = c.getLong(c.getColumnIndex("_id"));
			do {
				if(c.getString( c.getColumnIndex("google_id_key") ).length() > 0)
					google_id_key = c.getString( c.getColumnIndex("google_id_key") );
				
				if(c.getString( c.getColumnIndex("google_id") ).length() > 0)
					google_id = c.getString( c.getColumnIndex("google_id") );
				
				if(c.getString( c.getColumnIndex("name") ).length() > 0)
					author_name = c.getString( c.getColumnIndex("name") );
				
				if(c.getString( c.getColumnIndex("photo_url")).length() > 0)
					photo_url = c.getString( c.getColumnIndex("photo_url") );
			} while( c.moveToNext() && !(google_id_key != null && google_id != null && author_name != null && photo_url != null));	
			
			//update current author
			updateAuthorIDFull(author_id, google_id_key, google_id, author_name, photo_url, update_time);
			
			//remove others
			c.moveToFirst();
			do {
				if(c.getLong(c.getColumnIndex("_id")) != author_id)
					mDb.delete(DATABASE_TABLE_BUZZES, KEY_ROWID + "=" + c.getLong(c.getColumnIndex("_id")), null);
			} while( c.moveToNext());
			
			mAuthorWasCleaned = true;
			Log.w(TAG, "Clean finished");
		}
		c.close();
		return author_id;
	}
	
	/**
	 * Search for an existing Buzz in our DB 
	 * 
	 * @return the internal_buzz_id if found. Otherwise -1.
	 */
	public long findBuzzByGoogleBuzzId(String google_buzz_id)
	{
		String sql = "SELECT _id FROM buzzes WHERE google_buzz_id = '"+ google_buzz_id +"'";

		Cursor c = mDb.rawQuery(sql, null);
		long internal_buzz_id;
		int count = c.getCount();
		if (count == 1) {
			c.moveToFirst();
			int idx 			= c.getColumnIndex("_id");
			internal_buzz_id 	= c.getInt(idx);
		}
		else if(count == 0) {
			internal_buzz_id =  -1;
		}
		else {
			Log.w(TAG, "findBuzzByBuzzId google_buzz_id: "+ google_buzz_id + "-> more than one buzze found :"+count);
			internal_buzz_id =  -1;
		}
		c.close();
		return internal_buzz_id;
	}
	
	/**
	 * Search for an existing Comment in our DB 
	 * 
	 * @return the internal_comment_id if found. Otherwise -1.
	 */
	public long findCommentById(String comment_id)
	{
		String sql = "SELECT _id FROM comments WHERE comment_id = '"+ comment_id +"'";

		Cursor c = mDb.rawQuery(sql, null);
		long internal_comment_id;
		int count = c.getCount();
		if (count == 1) {
			c.moveToFirst();
			int idx 			= c.getColumnIndex("_id");
			internal_comment_id 	= c.getInt(idx);
		}
		else if(count == 0) {
			internal_comment_id =  -1;
		}
		else {
			Log.w(TAG, "findBuzzByBuzzId comment_id: "+ comment_id + "-> more than one comment found :"+count);
			internal_comment_id =  -1;
		}
		c.close();
		return internal_comment_id;
	}

	/**
	 * Check if requested new Follower/Following alredy exist for current profile.
	 * @param profileId The profile ID of current active account
	 * @param Name Requested new Followers/Following
	 * @param Email of Requested new Followers/Following
	 * @return
	 */
	public boolean isBuddyexist(String profileId, String Name, String Email) {
		// TODO Auto-generated method stub
		String sql = "SELECT name FROM " + DATABASE_TABLE_BUDDIES + " WHERE email = '" + Email + "' AND profiles_id = '" + profileId + "'";
		String buddyName;
		
		Cursor c = mDb.rawQuery(sql, null);
		int count = c.getCount();
		if (count == 1) {
			c.moveToFirst();
			int name = c.getColumnIndex("name");
			buddyName = c.getString(name);
			Log.d(TAG, "Found buddy: <" + buddyName + ">");
			if (Name.equals(buddyName)){
				Log.d(TAG, "Requested buddy already exist in database");
				return true;
			}
		}
		else if(count == 0) {
			return false;
		}
		c.close();
		return false;
	}
}
